package com.haojiang.mh.widget;

import android.animation.Animator;
import android.animation.AnimatorInflater;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;
import android.view.animation.Interpolator;
import android.widget.LinearLayout;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.viewpager.widget.ViewPager;
import com.haojiang.mh.R;
import com.haojiang.mh.utils.SizeUtil;

/**
 * (指定动画)自定义指示器
 * <p>
 * Created by ZapFive on 2019-05-25.
 * <p>
 * wuzhuang@mirahome.me
 */
public class CustomIndicator extends LinearLayout {
    private final static int DEFAULT_INDICATOR_WIDTH = 8;
    private float mMargin = -1;//相邻Margin
    private int mWidth = -1;//单个Indicator宽度
    private int mHeight = -1;//单个Indicator高度

    private int mAnimatorRsId = R.animator.indicator_scale;//默认Animator
    private int mAnimatorReverseRsId = 0;//反向Animator
    private int mIndicatorSelectBgRsId = R.drawable.shape_indicator_select;//选中Indicator背景
    private int mIndicatorNormalBgRsId = R.drawable.shape_indicator_normal;//没选中Indicator背景
    private Animator mAnimatorIn;//缩小
    private Animator mAnimatorOut;//放大
    private Animator mImmediateAnimatorIn;//直接缩小
    private Animator mImmediateAnimatorOut;//直接放大
    private boolean isNoAnimator = false, isNoBgLine = false;

    private RecyclerView mRecyclerView;
    private ViewPager mViewPager;
    private int mLastPosition = -1;
    private int mLineColor = 0XFF6900FF;
    private ViewPager.SimpleOnPageChangeListener indicatorPageChangerListener = new ViewPager.SimpleOnPageChangeListener() {

        @Override
        public void onPageSelected(int position) {
            if (mViewPager.getAdapter() != null && mViewPager.getAdapter().getCount() > 0) {
                if (!isNoAnimator && mAnimatorIn.isRunning()) {
                    mAnimatorIn.end();
                    mAnimatorIn.cancel();
                }

                if (!isNoAnimator && mAnimatorOut.isRunning()) {
                    mAnimatorOut.end();
                    mAnimatorOut.cancel();
                }

                View currIndicator;
                if (mLastPosition >= 0) {
                    currIndicator = getChildAt(mLastPosition);
                    if (currIndicator != null) {
                        currIndicator.setBackgroundResource(mIndicatorNormalBgRsId);
                        if (!isNoAnimator) {
                            mAnimatorIn.setTarget(currIndicator);
                            mAnimatorIn.start();
                        }
                    }
                }

                View selectIndicator = getChildAt(position);
                if (selectIndicator != null) {
                    selectIndicator.setBackgroundResource(mIndicatorSelectBgRsId);
                    if (!isNoAnimator) {
                        mAnimatorOut.setTarget(selectIndicator);
                        mAnimatorOut.start();
                    }
                }

                mLastPosition = position;
            }
        }
    };

    private RecyclerView.OnScrollListener mOnScrollChangeListener = new RecyclerView.OnScrollListener() {
        @Override
        public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
            super.onScrollStateChanged(recyclerView, newState);
            if (newState == RecyclerView.SCROLL_STATE_IDLE) {
                //rv静止后更新状态
                if (!isNoAnimator && mAnimatorIn.isRunning()) {
                    mAnimatorIn.end();
                    mAnimatorIn.cancel();
                }

                if (!isNoAnimator && mAnimatorOut.isRunning()) {
                    mAnimatorOut.end();
                    mAnimatorOut.cancel();
                }
                View currIndicator;
                if (mLastPosition >= 0) {
                    currIndicator = getChildAt(mLastPosition);
                    if (currIndicator != null) {
                        if (!isNoAnimator) {
                            mAnimatorIn.setTarget(currIndicator);
                            mAnimatorIn.start();
                        }
                    }
                }
                for (int i = 0; i < getChildCount(); i++) {
                    View view = getChildAt(i);
                    if (view != null) {
                        view.setBackgroundResource(mIndicatorNormalBgRsId);
                    }
                }
                int position = ((LinearLayoutManager) recyclerView.getLayoutManager()).findFirstVisibleItemPosition();
                View selectIndicator = getChildAt(position);
                if (selectIndicator != null) {
                    selectIndicator.setBackgroundResource(mIndicatorSelectBgRsId);
                    if (!isNoAnimator) {
                        mAnimatorOut.setTarget(selectIndicator);
                        mAnimatorOut.start();
                    }
                }

                mLastPosition = position;
            }
        }

        @Override
        public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
            super.onScrolled(recyclerView, dx, dy);
        }
    };

    public CustomIndicator(Context context) {
        this(context, null);
    }

    public CustomIndicator(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public CustomIndicator(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        init(context, attrs);
    }

    private void init(Context context, AttributeSet attrs) {

        handleTypedArray(context, attrs);

        initIndicatorConfig(context);

    }

    private void handleTypedArray(Context context, AttributeSet attrs) {

        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CustomIndicator);
        mMargin = a.getDimensionPixelOffset(R.styleable.CustomIndicator_cir_margin, 0);
        mWidth = a.getDimensionPixelOffset(R.styleable.CustomIndicator_cir_indicator_width, 0);
        mHeight = a.getDimensionPixelSize(R.styleable.CustomIndicator_cir_indicator_height, 0);
        isNoBgLine = a.getBoolean(R.styleable.CustomIndicator_cir_no_bgLine, false);
        if (!isNoBgLine) {
            mLineColor = a.getColor(R.styleable.CustomIndicator_cir_line_color, 0);
        }
        isNoAnimator = a.getBoolean(R.styleable.CustomIndicator_cir_no_animator, false);
        if (!isNoAnimator) {
            mAnimatorRsId = a.getResourceId(R.styleable.CustomIndicator_cir_animator, R.animator.indicator_scale);
            mAnimatorReverseRsId = a.getResourceId(R.styleable.CustomIndicator_cir_animator_reverse, 0);
        }
        mIndicatorSelectBgRsId = a.getResourceId(R.styleable.CustomIndicator_cir_select_drawable, R.drawable.shape_indicator_select);
        mIndicatorNormalBgRsId = a.getResourceId(R.styleable.CustomIndicator_cir_normal_drawable, R.drawable.shape_indicator_normal);

        int orientation = a.getInt(R.styleable.CustomIndicator_cir_orientation, -1);
        setOrientation(orientation == VERTICAL ? VERTICAL : HORIZONTAL);

        int gravity = a.getInt(R.styleable.CustomIndicator_cir_gravity, -1);
        setGravity(gravity >= 0 ? gravity : Gravity.CENTER);

        a.recycle();
    }

    private void initIndicatorConfig(Context context) {

        mMargin = (mMargin <= 0) ? SizeUtil.dp2px(context, DEFAULT_INDICATOR_WIDTH) : mMargin;
        mWidth = (mWidth <= 0) ? SizeUtil.dp2px(context, DEFAULT_INDICATOR_WIDTH) : mWidth;
        mHeight = (mHeight <= 0) ? SizeUtil.dp2px(context, DEFAULT_INDICATOR_WIDTH) : mHeight;
        mLineColor = (mLineColor == 0) ? 0xFF6900FF : mLineColor;

        if (isNoAnimator) return;
        mAnimatorRsId = (mAnimatorRsId == 0) ? R.animator.indicator_scale : mAnimatorRsId;
        mAnimatorIn = createAnimationIn(context);
        mImmediateAnimatorIn = createAnimationIn(context);
        mImmediateAnimatorIn.setDuration(0);
        mAnimatorOut = AnimatorInflater.loadAnimator(context, mAnimatorRsId);
        mImmediateAnimatorOut = AnimatorInflater.loadAnimator(context, mAnimatorRsId);
        mImmediateAnimatorOut.setDuration(0);
    }

    /**
     * 创建缩小动画
     */
    private Animator createAnimationIn(Context c) {
        Animator animator;
        if (mAnimatorReverseRsId == 0) {
            animator = AnimatorInflater.loadAnimator(c, mAnimatorRsId);
            animator.setInterpolator(new ReverseInterpolator());
        } else {
            animator = AnimatorInflater.loadAnimator(c, mAnimatorReverseRsId);
        }
        return animator;
    }

    /**
     * 创建指示器View
     */
    private void createIndicatorViews() {

        removeAllViews();
        int num = 0, orientation, currItemIndex = 0;
        if (mViewPager != null && mViewPager.getAdapter() != null) {
            num = mViewPager.getAdapter().getCount();
            if (num <= 0) return;
            currItemIndex = mViewPager.getCurrentItem();
        } else if (mRecyclerView != null && mRecyclerView.getAdapter() != null) {
            num = mRecyclerView.getAdapter().getItemCount();
            if (num <= 1) return;
            currItemIndex = ((LinearLayoutManager) mRecyclerView.getLayoutManager()).findFirstVisibleItemPosition();
        }
        orientation = getOrientation();
        for (int i = 0; i < num; i++) {
            if (currItemIndex == i) {
                addIndicator(orientation, mIndicatorSelectBgRsId, mImmediateAnimatorOut);
            } else {
                addIndicator(orientation, mIndicatorNormalBgRsId, mImmediateAnimatorIn);
            }
        }
        createBackgroundLine();

    }

    /**
     * 添加一个Indicator
     */
    private void addIndicator(int orientation, int bgDrawableRsId, Animator animator) {
        if (!isNoAnimator && animator.isRunning()) {
            animator.end();
            animator.cancel();
        }
        View indicator = new View(getContext());
        indicator.setBackgroundResource(bgDrawableRsId);
        addView(indicator, mWidth, mHeight);
        LayoutParams params = (LayoutParams) indicator.getLayoutParams();
        if (orientation == HORIZONTAL) {
            params.leftMargin = (int) mMargin;
            params.rightMargin = (int) mMargin;
        } else {
            params.topMargin = (int) mMargin;
            params.bottomMargin = (int) mMargin;
        }
        indicator.setLayoutParams(params);
        if (isNoAnimator) return;
        animator.setTarget(indicator);
        animator.start();
    }

    /**
     * 创建背景线
     */
    private void createBackgroundLine() {
        if (isNoBgLine) return;
        Drawable bgDrawable = new Drawable() {
            @Override
            public void draw(@NonNull Canvas canvas) {
                Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
                paint.setStyle(Paint.Style.FILL);
                paint.setColor(mLineColor);
                paint.setStrokeWidth(SizeUtil.dp2px(getContext(), 1));
                canvas.drawLine(
                        mMargin + mWidth * 0.5f,
                        getHeight() * 0.5f,
                        getWidth() - mMargin - mWidth * 0.5f,
                        getHeight() * 0.5f, paint
                );
            }

            @Override
            public void setAlpha(int alpha) {

            }

            @Override
            public void setColorFilter(ColorFilter colorFilter) {

            }

            @Override
            public int getOpacity() {
                return PixelFormat.UNKNOWN;
            }
        };
        setBackground(bgDrawable);
    }

    /**
     * 添加关联ViewPager
     */
    public void setViewPager(ViewPager viewPager) {
        this.mViewPager = viewPager;
        if (mViewPager != null && mViewPager.getAdapter() != null) {
            mLastPosition = -1;
            createIndicatorViews();
            mViewPager.removeOnPageChangeListener(indicatorPageChangerListener);
            mViewPager.addOnPageChangeListener(indicatorPageChangerListener);
            indicatorPageChangerListener.onPageSelected(mViewPager.getCurrentItem());
        }
    }

    public void setRecyclerView(RecyclerView recyclerView) {
        mRecyclerView = recyclerView;
        if (mRecyclerView != null && mRecyclerView.getAdapter() != null) {
            mLastPosition = -1;
            createIndicatorViews();
            mRecyclerView.removeOnScrollListener(mOnScrollChangeListener);
            mRecyclerView.addOnScrollListener(mOnScrollChangeListener);
        }
    }


    private class ReverseInterpolator implements Interpolator {

        @Override
        public float getInterpolation(float input) {
            return Math.abs(1.0f - input);
        }
    }
}
